package main

import (
	"fmt"
	"wzgames/internal/constant"
	"wzgames/internal/model/gkindp"
	"wzgames/internal/secure/rng"
	"wzgames/internal/services/games/gghotline"
	"wzgames/internal/services/games/ggkeno"
	"wzgames/internal/services/games/ggplinko"
	"wzgames/pkg/utils/stringutil"
)

func main() {
	//kenoAnalysis()
	plinkoAnalysis()
	//HotlineAnalysis()
}

func kenoAnalysis() {
	gift := &ggkeno.KenoGift{}
	gift.Init(nil)

	selNums := []int32{5, 6, 8, 12, 13, 14, 21, 23, 25, 33}
	ss := map[string]int64{"win": 0, "lose": 0, "draw": 0}
	for i := 0; i < 1000; i++ {
		serverSeed := rng.GenSeed(0, 0, 0)
		clientSeed := stringutil.RandomString(20)
		holds := gift.Calculate(serverSeed, clientSeed)
		m, _ := calcKeno(holds, selNums)
		if m < 1 {
			ss["lose"]++
		} else if m > 1 {
			ss["win"]++
		} else {
			ss["draw"]++
		}
	}
	fmt.Println(ss)
}

var kenoGameConfig = &gkindp.KenoGameConfig{
	Columns: 6,
	Rows:    6,
	SelMax:  10,
	Factors10: []*gkindp.KenoFactors{
		{Factors: []float64{3.49}},
		{Factors: []float64{1.5, 4.92}},
		{Factors: []float64{1, 2.3, 8.2}},
		{Factors: []float64{0.5, 1.82, 4.2, 21}},
		{Factors: []float64{0, 1.1, 3.75, 15, 35}},
		{Factors: []float64{0, 0.5, 2.9, 7.6, 18, 55}},
		{Factors: []float64{0, 0.25, 2.3, 4.1, 10, 31, 60}},
		{Factors: []float64{0, 0, 1.4, 2.8, 11.4, 28, 40, 70}},
		{Factors: []float64{0, 0, 1, 2.2, 6.1, 17, 25, 55, 85}},
		{Factors: []float64{0, 0, 1, 1.5, 3.3, 10.2, 25, 40, 75, 100}},
	},
}

func calcKeno(result []int32, selNums []int32) (float64, bool) {
	win := false
	mpResult := make(map[int32]bool)
	lRet := len(result)
	for i := 0; i < lRet; i++ {
		mpResult[result[i]] = true
	}
	var winNums []int32
	lQ := len(selNums)
	for i := 0; i < lQ; i++ {
		if _, ok := mpResult[selNums[i]]; ok {
			winNums = append(winNums, selNums[i])
		}
	}
	lWins := len(winNums)

	var multiplier float64
	if lWins > 0 {
		win = true
		multipliers := kenoGameConfig.Factors10[lQ-1]
		multiplier = multipliers.Factors[lWins-1]
		if multiplier <= 1 {
			win = false
		}
	}
	return multiplier, win
}

var plinkoGameConfig = &gkindp.PlinkoGameConfig{
	Pins: []int32{12, 14, 16},
	PinsPay: []*gkindp.PlinkoPinsPay{
		{
			Red:    []float64{141, 25, 8.1, 2.3, 0.7, 0.2, 0, 0.2, 0.7, 2.3, 8.1, 25, 141},
			Green:  []float64{11, 3.2, 1.6, 1.2, 1.1, 1, 0.5, 1, 1.1, 1.2, 1.6, 3.2, 11},
			Yellow: []float64{25, 8, 3.1, 1.7, 1.2, 0.7, 0.3, 0.7, 1.2, 1.7, 3.1, 8, 25},
		},
		{
			Red:    []float64{353, 49, 14, 5.3, 2.1, 0.5, 0.2, 0, 0.2, 0.5, 2.1, 5.3, 14, 49, 353},
			Green:  []float64{18, 3.2, 1.6, 1.3, 1.2, 1.1, 1, 0.5, 1, 1.1, 1.2, 1.3, 1.6, 3.2, 18},
			Yellow: []float64{55, 12, 5.6, 3.2, 1.6, 1, 0.7, 0.2, 0.7, 1, 1.6, 3.2, 5.6, 12, 55},
		},
		{
			Red:    []float64{555, 122, 26, 8.5, 3.5, 2, 0.5, 0.2, 0, 0.2, 0.5, 2, 3.5, 8.5, 26, 122, 555},
			Green:  []float64{35, 7.7, 2.5, 1.6, 1.3, 1.2, 1.1, 1, 0.4, 1, 1.1, 1.2, 1.3, 1.6, 2.5, 7.7, 35},
			Yellow: []float64{118, 61, 12, 4.5, 2.3, 1.2, 1, 0.7, 0.2, 0.7, 1, 1.2, 2.3, 4.5, 12, 61, 118},
		},
	},
}

func plinkoAnalysis() {
	gift := &ggplinko.Gift{}
	gift.Init(nil)

	selPins := int32(16)
	idx := 2
	colors := []string{constant.KeyRed, constant.KeyGreen, constant.KeyYellow}
	for x := 0; x < 3; x++ {
		color := colors[x]
		ss := map[string]int64{"win": 0, "lose": 0, "draw": 0}
		for i := 0; i < 1000; i++ {
			serverSeed := rng.GenSeed(0, 0, 0)
			clientSeed := stringutil.RandomString(20)
			result := gift.Calculate(serverSeed, clientSeed, selPins)
			m := getPlinkoPayout(idx, int(result), color)
			if m < 1 {
				ss["lose"]++
			} else if m > 1 {
				ss["win"]++
			} else {
				ss["draw"]++
			}
		}
		fmt.Println(color, ss)
	}
}

func getPlinkoPayout(idx, slot int, betType string) float64 {
	pinsPayout := plinkoGameConfig.PinsPay[idx]
	var multiplier = 1.0
	switch betType {
	case constant.KeyRed:
		if slot < len(pinsPayout.Red) {
			multiplier = pinsPayout.Red[slot]
		}
	case constant.KeyGreen:
		if slot < len(pinsPayout.Green) {
			multiplier = pinsPayout.Green[slot]
		}
	case constant.KeyYellow:
		if slot < len(pinsPayout.Yellow) {
			multiplier = pinsPayout.Yellow[slot]
		}
	}

	return multiplier
}

var hotlineGameConfig = &gkindp.HotlineGameConfig{
	Reg:    "2",
	RegRow: "4.125",
	HotRow: "1056",
	Hot:    "32",
}

func HotlineAnalysis() {
	gift := &gghotline.Gift{}
	gift.Init(nil)

	riskMode := false
	betColors := []string{constant.KeyRed, constant.KeyBlack, constant.KeyHot}
	for x := 0; x < 3; x++ {
		betColor := betColors[x]
		ss := map[string]int64{"win": 0, "lose": 0, "draw": 0}
		for i := 0; i < 1000; i++ {
			serverSeed := rng.GenSeed(0, 0, 0)
			clientSeed := stringutil.RandomString(20)
			result := gift.Calculate(serverSeed, clientSeed, riskMode)
			m, _ := calcHotlineResult(result, betColor, riskMode)
			if m < 1 {
				ss["lose"]++
			} else if m > 1 {
				ss["win"]++
			} else {
				ss["draw"]++
			}
		}
		fmt.Println(betColor, ss)
	}
}

func calcHotlineResult(result []string, betColor string, risk bool) (float64, bool) {
	win := false
	for i := 0; i < len(result); i++ {
		if risk {
			if result[i] != betColor {
				win = false
				break
			} else {
				win = true
			}
		} else {
			if result[i] == betColor {
				win = true
				break
			}
		}
	}

	var multiplier float64
	if win {
		multiplier = getHotlineMulitplier(betColor, risk)
	}
	return multiplier, win
}

func getHotlineMulitplier(color string, highrisk bool) float64 {
	var strVal string
	switch color {
	case constant.KeyRed, constant.KeyBlack:
		if highrisk {
			strVal = hotlineGameConfig.RegRow
		} else {
			strVal = hotlineGameConfig.Reg
		}
	case constant.KeyHot:
		if highrisk {
			strVal = hotlineGameConfig.HotRow
		} else {
			strVal = hotlineGameConfig.Hot
		}
	}

	ret, _ := stringutil.ToFloat64(strVal, 1.0)
	return ret
}
